package es.cazadoresmadridejos.beans.controller.biggame;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Random;
import java.util.Set;

import javax.servlet.http.HttpServletRequest;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.propertyeditors.CustomDateEditor;
import org.springframework.stereotype.Controller;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.ServletRequestDataBinder;
import org.springframework.web.bind.annotation.InitBinder;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.SessionAttributes;
import org.springframework.web.bind.support.SessionStatus;
import org.springframework.web.servlet.ModelAndView;

import es.cazadoresmadridejos.beans.manager.biggame.BigGameManager;
import es.cazadoresmadridejos.beans.manager.biggameassistance.BigGameAssistanceManager;
import es.cazadoresmadridejos.beans.manager.partner.PartnerManager;
import es.cazadoresmadridejos.beans.manager.session.UserPreferences;
import es.cazadoresmadridejos.beans.manager.temps.TempsManager;
import es.cazadoresmadridejos.beans.validator.biggame.BigGameValidator;
import es.cazadoresmadridejos.model.BigGame;
import es.cazadoresmadridejos.model.BigGame.BigGameName;
import es.cazadoresmadridejos.model.BigGame.BigGameStatus;
import es.cazadoresmadridejos.model.BigGameAssistance;
import es.cazadoresmadridejos.model.Partner;
import es.cazadoresmadridejos.model.Partner.Role;
import es.cazadoresmadridejos.model.Temps;
import es.cazadoresmadridejos.objs.web.Page;
import es.cazadoresmadridejos.objs.web.PaginatedListImpl;
import es.cazadoresmadridejos.propertyeditor.BigGamePropertyEditor;
import es.cazadoresmadridejos.util.constants.Constants;
import es.cazadoresmadridejos.util.validation.ValidationContainer;
import es.cazadoresmadridejos.web.util.ListUtil;

@SessionAttributes({"bigGame","partnersMap"})
@Controller
public class BigGameCreateModifyController {

	@Autowired private TempsManager tempsManager;
	@Autowired private BigGameManager bigGameManager;
	@Autowired private BigGameValidator bigGameValidator;
	@Autowired private PartnerManager partnerManager;
	@Autowired private BigGameAssistanceManager bigGameAssistanceManager;
//	@Autowired private MessageSource messageSource;
	@Autowired(required=false) private UserPreferences userPreferences;

	@InitBinder
	public void initBinder(HttpServletRequest request, ServletRequestDataBinder binder) throws Throwable{
		binder.registerCustomEditor(BigGame.class, new BigGamePropertyEditor(bigGameManager));
		binder.registerCustomEditor(Date.class, "date",new CustomDateEditor(Constants.sdf,true));
	}

	@RequestMapping(value="/bigGameCreateModify.html",method=RequestMethod.GET)
	public ModelAndView createModify(
			@RequestParam(value="id",required=false) BigGame bigGame,
			HttpServletRequest request) throws Throwable {
		ModelAndView mv = new ModelAndView();
		
		if(bigGame == null){
			bigGame = new BigGame();
			bigGame.setStatus(BigGameStatus.ABIERTA);
			mv.addObject("type", "create");
			bigGame.setReason(userPreferences.getReason());
		}else{
			bigGame.setAssistances(bigGameAssistanceManager.findAllByBigGame(bigGame.getId()));
			mv.addObject("type", "update");
			
			mv.addObject("closable", bigGame.getDate() != null && bigGame.getDate().getTime() > (new Date()).getTime());
		}
		

		if(BigGameStatus.EN_PROCESO.equals(bigGame.getStatus())){
			mv.addObject("editable", true);
		}else{
			BigGame bigGameInProgress = bigGameManager.getInProgressBigGame();
			if(bigGameInProgress != null){
				mv.addObject("editable", false);
			}else{
				mv.addObject("editable", true);
			}
		}
		
		mv.addObject("bigGame",bigGame);
		mv.addObject("bigGameNames",ListUtil.toString(BigGameName.values()));

		String string = partnerManager.findAllForAutocompleteBigGame(null);
		mv.addObject("partners",string);
		Page page = new Page(request);
		setModel(bigGame, mv, page);


		Set<Long> partnersMap = new HashSet<Long>();

		for (BigGameAssistance bga : bigGame.getAssistances()) {
			partnersMap.add(bga.getPartner().getId());
		}
		mv.addObject("partnersMap",partnersMap);
		return mv;
	}

	private void setModel(BigGame bigGame, ModelAndView mv, Page page) {
		page.setLimit(bigGame.getAssistances().size());
		page.setPage(1);
		page.setLimit(150);
		
		mv.addObject("partnersList",new PaginatedListImpl<BigGameAssistance>(bigGame.getAssistances(), page , bigGame.getAssistances().size()) );
		mv.addObject("size", bigGame.getAssistances().size());
		mv.addObject("currentPartner", userPreferences.getPartner().getId());
	}
	@RequestMapping(value="/bigGameCreateModifyAdd.html")
	public ModelAndView createModifyTable(
			@RequestParam(value="partnerId") Long partnerId,
			@ModelAttribute("bigGame") BigGame bigGame,
			@ModelAttribute("partnersMap") Set<Long> partnersMap,
			HttpServletRequest request) throws Throwable {
		ModelAndView mv = new ModelAndView("bigGameCreateModifyTable");

		if(!partnersMap.contains(partnerId)){
			BigGameAssistance bga = new BigGameAssistance();
			bga.setPartner(partnerManager.get(partnerId));
			bga.setBigGame(bigGame);

			bigGame.getAssistances().add(bga);
			partnersMap.add(partnerId);
		}
		Page page = new Page(request);
		setModel(bigGame, mv, page);
		mv.addObject("bigGame",bigGame);

		return mv;
	}
	@RequestMapping(value="/bigGameCreateModifyDelete.html")
	public ModelAndView createModifyTableDelete(
			@RequestParam(value="partnerId") Long partnerId,
			@ModelAttribute("bigGame") BigGame bigGame,
			@ModelAttribute("partnersMap") Set<Long> partnersMap,
			HttpServletRequest request) throws Throwable {
		ModelAndView mv = new ModelAndView("bigGameCreateModifyTable");

		if(partnersMap.contains(partnerId)){
			Iterator<BigGameAssistance> it = bigGame.getAssistances().iterator();
			while(it.hasNext()){
				BigGameAssistance bga = it.next();
				if(bga.getPartner().getId().equals(partnerId)){
					it.remove();
					partnersMap.remove(partnerId);
					break;
				}
			}
		}
		Page page = new Page(request);
		setModel(bigGame, mv, page);
		mv.addObject("bigGame",bigGame);

		return mv;
	}

	@RequestMapping(value="/bigGameCreateModify.html",method=RequestMethod.POST)
	public ModelAndView submit(
			@ModelAttribute("bigGame") BigGame bigGame, 
			BindingResult result, 
			SessionStatus status,
			HttpServletRequest request
			) throws Throwable {

		ModelAndView mv = new ModelAndView("redirect:index.html");
		mv.addObject("screen","bigGameList.html");

		List<ValidationContainer> errors = bigGameValidator.validate(bigGame);

		BigGame bigGameInProgress = bigGameManager.getInProgressBigGame();

		if(BigGameStatus.ABIERTA.equals(bigGame.getStatus())){
			//Si se modificado la lista y la montería estaba en estado ABIERTA se cambia a estado EN PROCESO
			if(bigGameInProgress != null){
				if(!bigGame.getAssistances().isEmpty()){
					bigGame.setStatus(BigGameStatus.EN_PROCESO);
				}
			}
		}
		//Seguridad
		if(BigGameStatus.CERRADA.equals(bigGame.getStatus())
				&& (bigGameInProgress != null && !bigGameInProgress.getId().equals(bigGame.getId()))
				){
			throw new Exception("Alguien ha intentado violar la seguridad");
		}
		
		if(errors.isEmpty()){
			 
			List<BigGameAssistance> list = bigGame.getAssistances();
			
			Collections.sort(list,new BigGameRandomComparator());
			
			Integer index = 1;
			for (BigGameAssistance bigGameAssistance : list) {
				bigGameAssistance.setListIndex(index);
				index++;
			}
			
			bigGameManager.save(bigGame);
			status.setComplete();
			mv.addObject("okMessage", "THE_BIGGAME_WAS_CREATED_SUCCESSFULLY");
		}else{
			mv.addObject("errors",errors);
		}


		return mv;
	}

	@RequestMapping(value="/bigGameAutoGenerate.html")
	public ModelAndView autoGenerate(
			@ModelAttribute("bigGame") BigGame bigGame,
			@RequestParam("stands") Integer stands,
			@ModelAttribute("partnersMap") Set<Long> partnersMap,
			HttpServletRequest request) throws Throwable {
		ModelAndView mv = new ModelAndView("bigGameCreateModifyTable");

		
		Temps temps = tempsManager.getByKey(Temps.BIG_GAME_ORDER);
		List<Role> roles = new ArrayList<Partner.Role>();
		roles.add(Role.CAZADOR);
		
		List<Partner> partners = partnerManager.findPartersFromOrderToBigGame(temps.getNumeric(), stands, true, false, partnersMap,roles);

		for (Partner partner : partners) {
			BigGameAssistance bga = new BigGameAssistance();
			bga.setPartner(partner);
			bga.setBigGame(bigGame);
			
			bigGame.getAssistances().add(bga);
		}
		
		
		Page page = new Page(request);
		setModel(bigGame, mv, page);
		mv.addObject("bigGame",bigGame);

		return mv;
	}
	
	class BigGameRandomComparator implements Comparator<BigGameAssistance>{

		@Override
		public int compare(BigGameAssistance o1, BigGameAssistance o2) {
			Random r = new Random();
			return r.nextInt();
		}
		
	}

}
